﻿using Innoapps.FileTransfer.Helpers;
using Innoapps.FileTransfer.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

namespace Innoapps.FileTransfer.Providers.State
{
    [XmlInclude(typeof (InProcess))]
    abstract public class Base
    {

        #region Structures
        internal struct StateListItem
        {
            public int? order;
            public string Action;
        }
        #endregion

        #region Variables
        internal XmlSerializerHelper<Models.Transfer> xmlHelperData = new XmlSerializerHelper<Models.Transfer>();

        internal List<StateListItem> stateList = new List<StateListItem>()
        {
            { new StateListItem() { order = 1, Action = "Innoapps.FileTransfer.Providers.State.Create" } },
            { new StateListItem() { order = 2, Action = "Innoapps.FileTransfer.Adapters.Receive.Receive" } },
            { new StateListItem() { order = 3, Action = "Innoapps.FileTransfer.Adapters.Send.Send" } },
            { new StateListItem() { order = 4, Action = "Innoapps.FileTransfer.Providers.Cache.Destroy" } },
            { new StateListItem() { order = 5, Action = "Innoapps.FileTransfer.Adapters.Receive.Delete" } },
            { new StateListItem() { order = 6, Action = "Innoapps.FileTransfer.Provisers.State.Complete" } }
        };

        #endregion

        #region Constructors
        public Base() { }
        #endregion

        #region Abstract Methods
        /// <summary>
        /// Logs an event for the specified transfer instance
        /// </summary>
        /// <param name="transfer">Data relating to the transfer of which the event is to be logged against</param>
        /// <param name="result">The event to be logged</param>
        abstract public void ProcessActionResult(Models.Transfer transfer);


        /// <summary>
        /// Retreives the next ready transfer
        /// </summary>
        abstract public Models.Transfer GetTransfer();

        /// <summary>
        /// Runs cleanup operations to remove the completed transfer from the state provider
        /// </summary>
        /// <param name="transfer">Completed transfer</param>
        abstract public void Complete(Transfer transfer);
        #endregion

        #region Internal Methods
        internal StateListItem GetNextState(string action)
        {
            int? current = (from r in stateList where r.Action == action select r.order).FirstOrDefault();

            return (from r in stateList where r.order == current + 1 select r).FirstOrDefault(); 

        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Adds a transfer to be handled by the state provider
        /// </summary>
        /// <param name="transfer">Data relating to the transfer to be added</param>
        public void Create(Models.Transfer transfer)
        {
            ActionResult e = new ActionResult("Innoapps.FileTransfer.Providers.State.Create", "Complete", "Success");

            transfer.ActionResults.Add(e);

            // If the transfer does not have an id then add one
            if (transfer.Id == null)
                transfer.Id = Guid.NewGuid();

            transfer.InProcess = true;
            transfer.NextAction = "Innoapps.FileTransfer.Providers.State.Create";
            transfer.NextAction_Scheduled = DateTime.Now;

            // Log the transfer
            ProcessActionResult(transfer);

        }
        #endregion


    }
}
